Element UI 之 Table 树形数据合并行的实现

您所在的位置:网站首页 el-table 树形结构数据 Element UI 之 Table 树形数据合并行的实现

Element UI 之 Table 树形数据合并行的实现

2024-01-22 03:55| 来源: 网络整理| 查看: 265

一、需求说明

Table 内容为树形结构,但需要合并收费项目重复列,具有子项的项目可展开和收起。如图:

二、遇到问题

1、表格数据格式

[{ id: 1, name: '篮网', item: '投篮(%)', value: Number.parseInt(Math.random() * 100), children: [{ id: 311, name: '詹姆斯·哈登', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 312, name: '詹姆斯·哈登', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 313, name: '詹姆斯·哈登', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }] }, { id: 2, name: '篮网', item: '三分(%)', value: Number.parseInt(Math.random() * 100), children: [{ id: 321, name: '詹姆斯·哈登', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 322, name: '詹姆斯·哈登', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 323, name: '詹姆斯·哈登', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }] }, { id: 3, name: '篮网', item: '罚球(%)', value: Number.parseInt(Math.random() * 100), children: [{ id: 31, name: '詹姆斯·哈登', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 32, name: '詹姆斯·哈登', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 33, name: '詹姆斯·哈登', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }] }]

2、表格未合并列前 3、期待合并效果 4、实际合并效果(注意观察项目列是否正确) 5、造成原因 通过打印第一列渲染内容,发现表格树形结构项无论是否展开、是父节点还是子节点,都是顺序执行渲染。这样,Table 标签的 rowspan 或者 colspan 属性所执行的合并行或合并列,合并机制都是按照渲染内容顺序来执行的。则没法做到我们想要的先合并父节点,再合并子节点。

三、解决思路

1、为达到先合并父节点,再合并子节点效果,可将上文提供的数据转为以下数据格式(相同父节点列表中最后一项保留子节点数据)。

[{ id: 1, name: '篮网', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 2, name: '篮网', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 3, name: '篮网', item: '罚球(%)', value: Number.parseInt(Math.random() * 100), children: [{ id: 31, name: '詹姆斯·哈登', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 32, name: '詹姆斯·哈登', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 33, name: '詹姆斯·哈登', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }] }]

2、可这样一来,发现表格无法展开。但若添加 default-expand-all 则能看到展开项,但依然无法切换树形表格是否展开与收起,造成原因是因为父节点列表中第一项没有 children 数据。 3、所幸的是,Element UI 给我们提供了 toggleRowExpansion 方法,我们可以通过给数据打标识和调用 toggleRowExpansion 方法来实现树形表格的展开与收起。

四、Demo 演示及代码

在真正的业务中,后端给前端的数据更可能是具有相关标识的扁平化数据。本文代码中,也是从扁平化数组整合为符合操作需求的树形结构数据。

// mock.js export const originTableData = [ { id: 1, parentId: 0, name: '篮网', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 2, parentId: 0, name: '篮网', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 3, parentId: 0, name: '篮网', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 31, parentId: 3, name: '詹姆斯·哈登', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 32, parentId: 3, name: '詹姆斯·哈登', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 33, parentId: 3, name: '詹姆斯·哈登', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 34, parentId: 3, name: '凯文·杜兰特', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 35, parentId: 3, name: '凯文·杜兰特', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 36, parentId: 3, name: '凯文·杜兰特', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 37, parentId: 3, name: '凯里·欧文', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 38, parentId: 3, name: '凯里·欧文', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 39, parentId: 3, name: '凯里·欧文', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 4, parentId: 0, name: '湖人', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 5, parentId: 0, name: '湖人', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 6, parentId: 0, name: '湖人', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 61, parentId: 6, name: '勒布朗·詹姆斯', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 62, parentId: 6, name: '勒布朗·詹姆斯', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 63, parentId: 6, name: '勒布朗·詹姆斯', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 64, parentId: 6, name: '安东尼·戴维斯', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 65, parentId: 6, name: '安东尼·戴维斯', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 66, parentId: 6, name: '安东尼·戴维斯', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 67, parentId: 6, name: '亚历克斯·卡鲁索', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 68, parentId: 6, name: '亚历克斯·卡鲁索', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 69, parentId: 6, name: '亚历克斯·卡鲁索', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 7, parentId: 0, name: '快船', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 8, parentId: 0, name: '快船', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 9, parentId: 0, name: '快船', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 91, parentId: 9, name: '保罗·乔治', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 92, parentId: 9, name: '保罗·乔治', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 93, parentId: 9, name: '保罗·乔治', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) }, { id: 94, parentId: 9, name: '科怀·伦纳德', item: '投篮(%)', value: Number.parseInt(Math.random() * 100) }, { id: 95, parentId: 9, name: '科怀·伦纳德', item: '三分(%)', value: Number.parseInt(Math.random() * 100) }, { id: 96, parentId: 9, name: '科怀·伦纳德', item: '罚球(%)', value: Number.parseInt(Math.random() * 100) } ] {{ row.name }} import { originTableData } from '../mock' export default { name: 'ExampleTable', data () { return { originTableData } }, computed: { formatTableData () { const data = [] this.originTableData.forEach(originItem => { const { id, parentId, name, item, value } = originItem const children = this.originTableData.filter(item => item.parentId === id) if (parentId === 0) { data.push({ id, name, item, value, children, isExpand: false }) } }) return data } }, methods: { checkHasChildren (row) { return this.formatTableData.filter(item => item.name === row.name) .some(item => item.children.length > 0) }, toggleRowExpansion (row) { row.isExpand = !row.isExpand // 此行代码有副作用,但目前只想到这样实现 const rowList = this.originTableData.filter(item => item.name === row.name) const expansionRow = rowList[rowList.length - 1] this.$refs.table && this.$refs.table.toggleRowExpansion(expansionRow, row.isExpand) }, objectSpanMethod ({ rowIndex, columnIndex }) { if (columnIndex === 0) { if (rowIndex % 3 === 0) { return { rowspan: 3, colspan: 1 } } else { return { rowspan: 0, colspan: 0 } } } } } } .cell-content { display: flex; justify-content: space-between; .arrow-icon { cursor: pointer; } } /deep/ .el-table__row.el-table__row--level-1 > td:first-child .cell .cell-content { padding-left: 30px; }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3